#include "syncmanager.h"
#include <QFile>
#include <QDebug>
#include <QCryptographicHash>

SyncManager::SyncManager(QObject *parent)
    : QObject(parent), totalFiles(0), copiedFiles(0), maxThreads(4) {}

void SyncManager::startSync(const QString &dirA, const QString &dirB, bool resolveConflicts) {
    // 记录开始同步的日志
    emit logMessage("开始同步");
    emit logMessage("同步目录: " + dirA);
    emit logMessage("待同步目录: " + dirB);
    QString Conflicts = "";
    if(resolveConflicts){
        Conflicts= "true";
    }else{
        Conflicts= "false";
    }
    emit logMessage("反向同步: " + Conflicts);

    totalFiles = calculateTotalFiles(dirA.toStdString()) + calculateTotalFiles(dirB.toStdString());
    copiedFiles = 0;


    copyDirectory(dirA.toStdString(), dirB.toStdString(), resolveConflicts);

    emit progressSyncUpdated(100); // 完成时进度为100%
    // 使用异步方式发送 finished 信号
    QMetaObject::invokeMethod(this, "emitFinished", Qt::QueuedConnection);
    // 记录同步完成的日志
    emit logMessage("同步任务已完成！");
}

void SyncManager::emitFinished() {
    emit finished();
}

// 拷贝文件
void SyncManager::copyFile(const std::string &source, const std::string &target, bool useMultiThread) {
    if (useMultiThread) {
        // 多线程拷贝大文件
        // 复用 BackupManager 中的多线程拷贝逻辑
    } else {
        // 单线程拷贝
        int src_fd = open(source.c_str(), O_RDONLY);
        if (src_fd == -1) {
            std::cerr << "Failed to open source file: " << source << " - " << strerror(errno) << std::endl;
            return;
        }

        int dst_fd = open(target.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
        if (dst_fd == -1) {
            close(src_fd);
            std::cerr << "Failed to open target file: " << target << " - " << strerror(errno) << std::endl;
            return;
        }

        char buffer[4096];
        ssize_t bytesRead;

        while ((bytesRead = read(src_fd, buffer, sizeof(buffer))) > 0) {
            if (write(dst_fd, buffer, bytesRead) != bytesRead) {
                std::cerr << "Failed to write to target file: " << target << " - " << strerror(errno) << std::endl;
                close(src_fd);
                close(dst_fd);
                return;
            }
        }

        if (bytesRead == -1) {
            std::cerr << "Failed to read from source file: " << source << " - " << strerror(errno) << std::endl;
        }

        close(src_fd);
        close(dst_fd);

        ++copiedFiles;
        if (totalFiles != 0) {
            int progress = (copiedFiles * 100) / totalFiles;
            emit progressSyncUpdated(progress);
        }
    }

    // 记录文件同步完成的日志
    emit logMessage("文件同步完成: " + QString::fromStdString(source));
}

// 线程入口点
void* SyncManager::fileCopyThread(void* arg) {
    // 复用 BackupManager 中的多线程拷贝逻辑
    return nullptr;
}

// 拷贝路径
void SyncManager::copyDirectory(const std::string &dirA, const std::string &dirB, bool resolveConflicts) {
    // 打开源目录
    DIR *dir = opendir(dirA.c_str());
    if (!dir) {
        std::cerr << "Failed to open directory: " << dirA << " - " << strerror(errno) << std::endl;
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != nullptr) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        std::string filePathA = dirA + "/" + entry->d_name;
        std::string filePathB = dirB + "/" + entry->d_name;

        struct stat fileInfoA = getFileStat(filePathA);
        struct stat fileInfoB;

        if (S_ISDIR(fileInfoA.st_mode)) {
            if (!createDirectoryIfNotExists(filePathB)) {
                std::cerr << "Failed to create directory: " << filePathB << std::endl;
                continue;
            }
            copyDirectory(filePathA, filePathB, resolveConflicts);
        } else {
            if (lstat(filePathB.c_str(), &fileInfoB) == 0) {
                if (S_ISREG(fileInfoB.st_mode)) {
                    // 比较文件属性和内容
                    if (fileInfoA.st_mtime > fileInfoB.st_mtime||
                        fileInfoA.st_size != fileInfoB.st_size ||
                        fileInfoA.st_mode != fileInfoB.st_mode ||
                        getFileChecksum(filePathA) != getFileChecksum(filePathB)) {

                        if (resolveConflicts) {
                            // 冲突解决逻辑
                            // 可以选择询问用户或总是使用较新的文件等
                            copyFile(filePathA, filePathB, false);
                        }else{
                            // 直接覆盖
                            copyFile(filePathB, filePathA, false);
                        }
                    }
                } else {
                    // 如果目标不是文件，则删除并复制
                    remove(filePathB.c_str());
                    copyFile(filePathA, filePathB, false);
                }
            } else {
                // 目标文件不存在，直接复制
                copyFile(filePathA, filePathB, false);
            }
        }
    }

    closedir(dir);
}

// 计算要拷贝目录下文件的总数
int SyncManager::calculateTotalFiles(const std::string &dirPath) {
    int count = 0;
    DIR *dir = opendir(dirPath.c_str());
    if (!dir) {
        std::cerr << "Failed to open directory: " << dirPath << " - " << strerror(errno) << std::endl;
        return 0;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != nullptr) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        std::string filePath = dirPath + "/" + entry->d_name;
        struct stat fileInfo = getFileStat(filePath);
        if (S_ISREG(fileInfo.st_mode)) {
            ++count;
        } else if (S_ISDIR(fileInfo.st_mode)) {
            count += calculateTotalFiles(filePath);
        }
    }

    closedir(dir);
    return count;
}

// 创建目录如果不存在
bool SyncManager::createDirectoryIfNotExists(const std::string &dirPath) {
    if (mkdir(dirPath.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1 && errno != EEXIST) {
        std::cerr << "Failed to create directory: " << dirPath << " - " << strerror(errno) << std::endl;
        return false;
    }
    return true;
}

// 获取文件状态
struct stat SyncManager::getFileStat(const std::string &filePath) {
    struct stat fileInfo;
    if (stat(filePath.c_str(), &fileInfo) == -1) {
        std::cerr << "Failed to get file info: " << filePath << " - " << strerror(errno) << std::endl;
        memset(&fileInfo, 0, sizeof(fileInfo));
    }
    return fileInfo;
}

// 获取文件校验和
QByteArray SyncManager::getFileChecksum(const std::string &filePath) {
    QFile file(QString::fromStdString(filePath));
    if (!file.open(QIODevice::ReadOnly)) {
        std::cerr << "Failed to open file for checksum: " << filePath << " - " << strerror(errno) << std::endl;
        return QByteArray();
    }

    QCryptographicHash hash(QCryptographicHash::Md5);
    if (!hash.addData(&file)) {
        std::cerr << "Failed to add data to hash" << std::endl;
        return QByteArray();
    }

    return hash.result().toHex();
}
